package jmine.tec.scheduling.web.pages.task.execution;

import static jmine.tec.web.wicket.pages.form.WebFormPagesMessages.ERROR_CANNOT_FIND_ENTITY_TO_VIEW;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jmine.tec.report.impl.table.ReportTableBuilder;
import jmine.tec.scheduling.dao.ScheduledTaskDAO;
import jmine.tec.scheduling.dao.ScheduledTaskExecutionDAO;
import jmine.tec.scheduling.domain.ScheduledTask;
import jmine.tec.scheduling.domain.ScheduledTaskExecution;
import jmine.tec.scheduling.domain.ScheduledTaskExecutionStatus;
import jmine.tec.web.wicket.component.command.img.ImageCommand;
import jmine.tec.web.wicket.component.command.img.ViewCommand;
import jmine.tec.web.wicket.component.command.img.ViewCommandHandler;
import jmine.tec.web.wicket.pages.form.ListPage;
import jmine.tec.web.wicket.spring.SpringBeanReference;

import org.apache.wicket.Page;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.model.PropertyModel;
import org.hibernate.criterion.Order;

import bancosys.tec.exception.BusinessException;
import bancosys.tec.exception.MessageCreator;
import bancosys.tec.persist.dao.BaseDAOFactory;
import bancosys.tec.persist.dao.BeanNotFoundException;
import bancosys.tec.security.annotation.Secure;
import bancosys.tec.security.authorization.UrlPermission;
import bancosys.tec.utils.date.Date;
import bancosys.tec.utils.date.Time;
import bancosys.tec.utils.date.Timestamp;

/**
 * Lists scheduled tasks
 * 
 * @author lundberg
 */
@Secure(id = "URL_LIST_SCHEDULED_TASK_EXECUTION", permissionType = UrlPermission.class)
public class ListScheduledTaskExecutionPage extends ListPage<ScheduledTaskExecution, ScheduledTaskExecution> implements ViewCommandHandler {

    private static final int SECONDS_GROUP = 3;

    private static final Time BEFORE_MIDNIGHT = new Time(23, 59, 59);

    private Date startDate = new Date();

    private Date endDate = new Date();

    private String startHorario;

    private String endHorario;

    /**
     * {@inheritDoc}
     */
    @Override
    protected ScheduledTaskExecution createModel() {
        return this.daoFactoryRef.get().getGenericDAO(ScheduledTaskExecution.class).createBean();
    }

    /**
     * {@inheritDoc}
     */
    public Page createNewPage() {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    public List<ScheduledTaskExecution> search(BaseDAOFactory daoFactory) {
        ScheduledTaskExecutionDAO dao = daoFactory.getDAOByClass(ScheduledTaskExecutionDAO.class);
        ScheduledTaskExecution model = this.getModel();

        Calendar startDateCal = Calendar.getInstance();
        startDateCal.setTime(this.startDate);
        Calendar finalDateCal = Calendar.getInstance();
        finalDateCal.setTime(this.endDate);

        Timestamp timestampIni;
        if (this.startHorario != null) {
            timestampIni = new Timestamp(new Date(startDateCal.getTimeInMillis()), this.getTime(this.startHorario));
        } else {
            timestampIni = new Timestamp(new Date(startDateCal.getTimeInMillis()), new Time(0, 0, 0));
        }

        Timestamp timestampEnd;
        if (this.endHorario != null) {
            timestampEnd = new Timestamp(new Date(finalDateCal.getTimeInMillis()), this.getTime(this.endHorario));
        } else {
            timestampEnd = new Timestamp(new Date(finalDateCal.getTimeInMillis()), BEFORE_MIDNIGHT);
        }
        return dao.findByTaskStatusDate(model.getTask(), model.getStatus(), timestampIni, timestampEnd, Order.desc("end"));
    }

    /**
     * Faz o parser da string de hora no formato hh:mm:ss e converte para Time.
     * 
     * @param hora no formato hh:mm:ss
     * @return a hora como um objeto Time
     */
    private Time getTime(String hora) {
        Pattern hourPattern = Pattern.compile("(\\d\\d):(\\d\\d):(\\d\\d)");
        Matcher m = hourPattern.matcher(hora);
        if (m.matches()) {
            return new Time(Integer.valueOf(m.group(1)), Integer.valueOf(m.group(2)), Integer.valueOf(m.group(SECONDS_GROUP)));
        } else {
            return new Time(0, 0, 0);
        }
    }

    /**
     * List all available tasks
     * 
     * @return List of ScheduledTask
     */
    private List<ScheduledTask> listTasks() {
        ScheduledTaskDAO dao = SpringBeanReference.forType(ScheduledTaskDAO.class).get();
        return dao.findAll();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void addSearchFields(WebMarkupContainer container) {
        DropDownChoice<ScheduledTask> taskDropDown = this.createDropDown("task", this.getModel(), "task", this.listTasks());
        taskDropDown.setRequired(false);
        taskDropDown.setNullValid(true);
        container.add(taskDropDown);

        DropDownChoice<ScheduledTaskExecutionStatus> statusDropDown =
                this.createDropDown("status", this.getModel(), "status", Arrays.asList(ScheduledTaskExecutionStatus.values()));
        statusDropDown.setRequired(false);
        statusDropDown.setNullValid(true);
        container.add(statusDropDown);

        container.add(this.createDateField("startDate", new PropertyModel<Date>(this, "startDate")));
        container.add(this.createDateField("endDate", new PropertyModel<Date>(this, "endDate")));
        container.add(this.createTextField("startHorario", new PropertyModel<String>(this, "startHorario")));
        container.add(this.createTextField("endHorario", new PropertyModel<String>(this, "endHorario")));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void addResultTableColumns(ReportTableBuilder<ScheduledTaskExecution> table) {
        table.addStringColumn("task", "Tarefa", "task");
        table.addStringColumn("status", "Status", "status");
        table.addStringColumn("start", "Início da execução", "start");
        table.addStringColumn("fim", "Fim da execução", "end");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected MessageCreator getHelpTextCreator() {
        return null;
    }

    /**
     * Creates the view page
     * 
     * @param entityPk entityPk
     * @return page
     */
    public Page createViewPage(Serializable entityPk) {
        try {
            ScheduledTaskExecution entity = this.loadEntity(entityPk);
            return new DetalheScheduledTaskExecutionPage(this, entity);
        } catch (BeanNotFoundException e) {
            throw new BusinessException(ERROR_CANNOT_FIND_ENTITY_TO_VIEW.create(this.getPageName(), entityPk));
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected List<ImageCommand> getTableCommands(ScheduledTaskExecution entity) {
        List<ImageCommand> commands = new ArrayList<ImageCommand>();
        commands.add(new ViewCommand(this));
        return commands;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean shouldIncludeTableCommands() {
        return true;
    }

}
